<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Java基础1-Spring特点是什么 | Hexo</title>
  <meta name="keywords" content="">
  <meta name="description" content="Java基础1-Spring特点是什么 | Hexo">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick">
<meta property="og:type" content="article">
<meta property="og:title" content="Hello World">
<meta property="og:url" content="http://yoursite.com/2020/07/27/hello-world/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2020-07-27T05:17:47.002Z">
<meta property="article:modified_time" content="2020-07-27T05:17:47.002Z">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">


<link rel="icon" href="/img/avatar.jpg">

<link href="/css/style.css?v=1.1.0" rel="stylesheet">

<link href="/css/hl_theme/atom-light.css?v=1.1.0" rel="stylesheet">

<link href="//cdn.jsdelivr.net/npm/animate.css@4.1.0/animate.min.css" rel="stylesheet">

<script src="//cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<script src="/js/titleTip.js?v=1.1.0" ></script>

<script src="//cdn.jsdelivr.net/npm/highlightjs@9.16.2/highlight.pack.min.js"></script>
<script>
    hljs.initHighlightingOnLoad();
</script>

<script src="//cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js"></script>



<script src="//cdn.jsdelivr.net/npm/jquery.cookie@1.4.1/jquery.cookie.min.js" ></script>

<script src="/js/iconfont.js?v=1.1.0" ></script>

<meta name="generator" content="Hexo 4.2.1"></head>
<div style="display: none">
  <input class="theme_disqus_on" value="false">
  <input class="theme_preload_comment" value="">
  <input class="theme_blog_path" value="">
  <input id="theme_shortcut" value="true" />
</div>


<body>
<aside class="nav">
    <div class="nav-left">
        <a href="/" class="avatar_target">
    <img class="avatar" src="/img/avatar.jpg" />
</a>
<div class="author">
    <span>John Doe</span>
</div>

<div class="icon">
    
        
        <a title="rss" href="/atom.xml" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-rss"></use>
                </svg>
            
        </a>
        
    
        
        <a title="github" href="https://github.com/yelog" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-github"></use>
                </svg>
            
        </a>
        
    
        
        <a title="facebook" href="https://www.facebook.com/faker.tops" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-facebook"></use>
                </svg>
            
        </a>
        
    
        
    
        
    
        
        <a title="instagram" href="https://www.facebook.com/faker.tops" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-instagram"></use>
                </svg>
            
        </a>
        
    
        
        <a title="reddit" href="https://www.reddit.com/user/yelog/" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-reddit"></use>
                </svg>
            
        </a>
        
    
        
        <a title="weibo" href="http://weibo.com/u/2307534817" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-weibo"></use>
                </svg>
            
        </a>
        
    
        
        <a title="jianshu" href="https://www.jianshu.com/u/ff56736de7cf" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-jianshu"></use>
                </svg>
            
        </a>
        
    
        
        <a title="zhihu" href="https://www.zhihu.com/people/jaytp/activities" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-zhihu"></use>
                </svg>
            
        </a>
        
    
        
    
        
        <a title="oschina" href="https://my.oschina.net/yelog" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-oschina"></use>
                </svg>
            
        </a>
        
    
        
    
        
        <a title="email" href="mailto:jaytp@qq.com" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-email"></use>
                </svg>
            
        </a>
        
    
        
        <a title="qq" href="http://wpa.qq.com/msgrd?v=3&uin=872336115&site=qq&menu=yes" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-qq"></use>
                </svg>
            
        </a>
        
    
        
        <a title="kugou" href="https://www.kugou.com/" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-kugou"></use>
                </svg>
            
        </a>
        
    
        
        <a title="neteasemusic" href="https://music.163.com/#/user/home?id=88151013" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-neteasemusic"></use>
                </svg>
            
        </a>
        
    
</div>




<ul>
    <li><div class="all active" data-rel="All">All<small>(10)</small></div></li>
    
        
            
            <li><div data-rel="后端">后端<small>(3)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="Java基础">Java基础<small>(4)</small></div>
                
            </li>
            
        
    
</ul>
<div class="left-bottom">
    <div class="menus">
    
    
    
    
    </div>
    <div><a class="about  hasFriend  site_url"  href="/about">About</a><a style="width: 50%"  class="friends">Friends</a></div>
</div>
<input type="hidden" id="yelog_site_posts_number" value="10">

<div style="display: none">
    <span id="busuanzi_value_site_uv"></span>
    <span id="busuanzi_value_site_pv"></span>
</div>

    </div>
    <div class="nav-right">
        <div class="friends-area">
    <div class="friends-title">
        Links
        <i class="iconfont icon-left"></i>
    </div>
    <div class="friends-content">
        <ul>
            
            <li><a target="_blank" href="http://yelog.org/">叶落阁</a></li>
            
        </ul>
    </div>
</div>
        <div class="title-list">
    <div class="right-top">
        <div id="default-panel">
            <i class="iconfont icon-search" data-title="搜索 快捷键 i"></i>
            <div class="right-title">All</div>
            <i class="iconfont icon-file-tree" data-title="切换到大纲视图 快捷键 w"></i>
        </div>
        <div id="search-panel">
            <i class="iconfont icon-left" data-title="返回"></i>
            <input id="local-search-input" />
            <label class="border-line" for="input"></label>
            <i class="iconfont icon-case-sensitive" data-title="大小写敏感"></i>
            <i class="iconfont icon-tag" data-title="标签"></i>
        </div>
        <div id="outline-panel" style="display: none">
            <div class="right-title">大纲</div>
            <i class="iconfont icon-list" data-title="切换到文章列表"></i>
        </div>
    </div>

    <div class="tags-list">
    <input id="tag-search" />
    <div class="tag-wrapper">
        
            <li class="article-tag-list-item">
                <i class="iconfont icon-tag"></i><a>Git</a>
            </li>
        
    </div>

</div>

    
    <nav id="title-list-nav">
        
        <a  class="All "
           href="/2020/07/27/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E9%98%B6%E6%AE%B5/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="微服务阶段">微服务阶段</span>
            <span class="post-date" title="2020-07-27 14:31:06">2020/07/27</span>
        </a>
        
        <a  class="All "
           href="/2020/07/27/hello-world/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="Hello World">Hello World</span>
            <span class="post-date" title="2020-07-27 13:17:47">2020/07/27</span>
        </a>
        
        <a  class="All "
           href="/2020/07/23/Java%E5%9F%BA%E7%A1%805/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="Java基础5-">Java基础5-</span>
            <span class="post-date" title="2020-07-23 23:51:18">2020/07/23</span>
        </a>
        
        <a  class="All Java基础 "
           href="/2020/07/21/Java%E5%9F%BA%E7%A1%804-%E8%AF%A6%E8%A7%A3-ThreadPoolExecutor-%E7%9A%84%E5%8F%82%E6%95%B0%E5%90%AB%E4%B9%89%E5%8F%8A%E6%BA%90%E7%A0%81%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="java基础4-详解 ThreadPoolExecutor 的参数含义及源码执行流程">java基础4-详解 ThreadPoolExecutor 的参数含义及源码执行流程</span>
            <span class="post-date" title="2020-07-21 21:53:39">2020/07/21</span>
        </a>
        
        <a  class="All Java基础 "
           href="/2020/07/20/Java%E5%9F%BA%E7%A1%803-%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%8A%B6%E6%80%81%E6%9C%89%E5%93%AA%E4%BA%9B/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="Java基础3-线程的状态有哪些">Java基础3-线程的状态有哪些</span>
            <span class="post-date" title="2020-07-20 10:21:12">2020/07/20</span>
        </a>
        
        <a  class="All Java基础 "
           href="/2020/07/17/Java%E5%9F%BA%E7%A1%802-HashMap%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="Java基础2-HashMap底层原理">Java基础2-HashMap底层原理</span>
            <span class="post-date" title="2020-07-17 13:02:46">2020/07/17</span>
        </a>
        
        <a  class="All Java基础 "
           href="/2020/07/13/Java%E5%9F%BA%E7%A1%801-Spring%E7%89%B9%E7%82%B9%E6%98%AF%E4%BB%80%E4%B9%88/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="Java基础1-Spring特点是什么">Java基础1-Spring特点是什么</span>
            <span class="post-date" title="2020-07-13 17:24:53">2020/07/13</span>
        </a>
        
        <a  class="All 后端 "
           href="/2020/07/09/%E4%BD%BF%E7%94%A8SSH%E5%AF%86%E9%92%A5%E8%BF%9E%E6%8E%A5Github/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="使用SSH密钥连接Github">使用SSH密钥连接Github</span>
            <span class="post-date" title="2020-07-09 18:13:36">2020/07/09</span>
        </a>
        
        <a  class="All 后端 "
           href="/2020/07/09/%E6%89%8B%E6%8A%8A%E6%89%8B%E6%95%99%E4%BD%A0%E4%BB%8E0%E5%BC%80%E5%A7%8B%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="手把手教你从0开始搭建个人博客">手把手教你从0开始搭建个人博客</span>
            <span class="post-date" title="2020-07-09 17:27:06">2020/07/09</span>
        </a>
        
        <a  class="All 后端 "
           href="/2020/07/08/Git%E5%AE%89%E8%A3%85/"
           data-tag="Git"
           data-author="" >
            <span class="post-title" title="Git安装">Git安装</span>
            <span class="post-date" title="2020-07-08 13:04:43">2020/07/08</span>
        </a>
        
        <div id="no-item-tips">

        </div>
    </nav>
    <div id="outline-list">
    </div>
</div>
    </div>
    <div class="hide-list">
        <div class="semicircle" data-title="切换全屏 快捷键 s">
            <div class="brackets first"><</div>
            <div class="brackets">&gt;</div>
        </div>
    </div>
</aside>
<div id="post">
    <div class="pjax">
        <article id="post-Java基础1-Spring特点是什么" class="article article-type-post" itemscope itemprop="blogPost">
    
        <h1 class="article-title">Java基础1-Spring特点是什么</h1>
    
    <div class="article-meta">
        
        
        
        <span class="book">
            <i class="iconfont icon-category"></i>
            
            <a  data-rel="Java基础">Java基础</a>
            
        </span>
        
        
    </div>
    <div class="article-meta">
        
            Created At : <time class="date" title='Updated At: 2020-07-21 21:38:39'>2020-07-13 17:24</time>
        
    </div>
    <div class="article-meta">
        
        
        <span id="busuanzi_container_page_pv">
            Views 👀 :<span id="busuanzi_value_page_pv">
                <span class="count-comment">
                    <span class="spinner">
                      <div class="cube1"></div>
                      <div class="cube2"></div>
                    </span>
                </span>
            </span>
        </span>
        
        
    </div>
    
    <div class="toc-ref">
    
        <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#一、String-是如何实现的"><span class="toc-text">一、String 是如何实现的</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#二、它有哪些重要的方法"><span class="toc-text">二、它有哪些重要的方法</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#String-源码中包含下面几个重要的方法。"><span class="toc-text">String 源码中包含下面几个重要的方法。</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-1-多构造方法"><span class="toc-text">2.1. 多构造方法</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-2-equals-比较两个字符串是否相等"><span class="toc-text">2.2. equals() 比较两个字符串是否相等</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-3-compareTo-比较两个字符串"><span class="toc-text">2.3. compareTo() 比较两个字符串</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-4-其他重要方法"><span class="toc-text">2.4. 其他重要方法</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#三、知识扩展"><span class="toc-text">三、知识扩展</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#3-1-和-equals-的区别"><span class="toc-text">3.1. &#x3D;&#x3D; 和 equals 的区别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-2-final-修饰的好处"><span class="toc-text">3.2. final 修饰的好处</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-3-String-和-StringBuilder、StringBuffer-的区别"><span class="toc-text">3.3. String 和 StringBuilder、StringBuffer 的区别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-4-String-和-JVM"><span class="toc-text">3.4. String 和 JVM</span></a></li></ol></li></ol>
    
<style>
    .left-col .switch-btn,
    .left-col .switch-area {
        display: none;
    }
    .toc-level-3 i,
    .toc-level-3 ol {
        display: none !important;
    }
</style>
</div>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="一、String-是如何实现的"><a href="#一、String-是如何实现的" class="headerlink" title="一、String 是如何实现的"></a>一、String 是如何实现的</h1><blockquote>
<p>以主流的 JDK 版本 1.8 来说，String 内部实际存储结构为 char 数组，源码如下：</p>
</blockquote>
<pre class="brush: java">
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    // 用于存储字符串的值
    private final char value[];
    // 缓存字符串的 hash code
    private int hash; // Default to 0
    // ......其他内容
}
</pre>

<hr>
<h1 id="二、它有哪些重要的方法"><a href="#二、它有哪些重要的方法" class="headerlink" title="二、它有哪些重要的方法"></a>二、它有哪些重要的方法</h1><hr>
<h2 id="String-源码中包含下面几个重要的方法。"><a href="#String-源码中包含下面几个重要的方法。" class="headerlink" title="String 源码中包含下面几个重要的方法。"></a>String 源码中包含下面几个重要的方法。</h2><hr>
<h2 id="2-1-多构造方法"><a href="#2-1-多构造方法" class="headerlink" title="2.1. 多构造方法"></a>2.1. 多构造方法</h2><blockquote>
<p>String 字符串有以下 4 个重要的构造方法：</p>
</blockquote>
<pre class="brush: java">
// String 为参数的构造方法
public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}
// char[] 为参数构造方法
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}
// StringBuffer 为参数的构造方法
public String(StringBuffer buffer) {
    synchronized(buffer) {
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}
// StringBuilder 为参数的构造方法
public String(StringBuilder builder) {
    this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
</pre>

<blockquote>
<p>其中，比较容易被我们忽略的是以 StringBuffer 和 StringBuilder 为参数的构造函数，因为这三种数据类型，我们通常都是单独使用的，所以这个小细节我们需要特别留意一下。</p>
</blockquote>
<hr>
<h2 id="2-2-equals-比较两个字符串是否相等"><a href="#2-2-equals-比较两个字符串是否相等" class="headerlink" title="2.2. equals() 比较两个字符串是否相等"></a>2.2. equals() 比较两个字符串是否相等</h2><p>源码如下：</p>
<pre class="brush: java">
public boolean equals(Object anObject) {
    // 对象引用相同直接返回 true
    if (this == anObject) {
        return true;
    }
    // 判断需要对比的值是否为 String 类型，如果不是则直接返回 false
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            // 把两个字符串都转换为 char 数组对比
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            // 循环比对两个字符串的每一个字符
            while (n-- != 0) {
                // 如果其中有一个字符不相等就 true false，否则继续对比
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
</pre>

<blockquote>
<p>String 类型重写了 Object 中的 equals() 方法，equals() 方法需要传递一个 Object 类型的参数值，在比较时会先通过 instanceof 判断是否为 String 类型，如果不是则会直接返回 false，instanceof 的使用如下：</p>
</blockquote>
<pre class="brush:java">
Object oString = "123";
Object oInt = 123;
System.out.println(oString instanceof String); // 返回 true
System.out.println(oInt instanceof String); // 返回 false
</pre>

<blockquote>
<p>当判断参数为 String 类型之后，会循环对比两个字符串中的每一个字符，当所有字符都相等时返回 true，否则则返回 false。<br>还有一个和 equals() 比较类似的方法 equalsIgnoreCase()，它是用于忽略字符串的大小写之后进行字符串对比。</p>
</blockquote>
<hr>
<h2 id="2-3-compareTo-比较两个字符串"><a href="#2-3-compareTo-比较两个字符串" class="headerlink" title="2.3. compareTo() 比较两个字符串"></a>2.3. compareTo() 比较两个字符串</h2><blockquote>
<p>compareTo() 方法用于比较两个字符串，返回的结果为 int 类型的值</p>
</blockquote>
<p>源码如下：</p>
<pre class="brush:java">
public int compareTo(String anotherString) {
    int len1 = value.length;
    int len2 = anotherString.value.length;
    // 获取到两个字符串长度最短的那个 int 值
    int lim = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;
    int k = 0;
    // 对比每一个字符
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            // 有字符不相等就返回差值
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
}
</pre>

<blockquote>
<p>从源码中可以看出，compareTo() 方法会循环对比所有的字符，当两个字符串中有任意一个字符不相同时，则 return char1-char2。比如，两个字符串分别存储的是 1 和 2，返回的值是 -1；如果存储的是 1 和 1，则返回的值是 0 ，如果存储的是 2 和 1，则返回的值是 1。还有一个和 compareTo() 比较类似的方法 compareToIgnoreCase()，用于忽略大小写后比较两个字符串。可以看出 compareTo() 方法和 equals() 方法都是用于比较两个字符串的，但它们有两点不同：</p>
</blockquote>
<ul>
<li><p>equals() 可以接收一个 Object 类型的参数，而 compareTo() 只能接收一个 String 类型的参数；</p>
</li>
<li><p>equals() 返回值为 Boolean，而 compareTo() 的返回值则为 int。<br>它们都可以用于两个字符串的比较，当 equals() 方法返回 true 时，或者是 compareTo() 方法返回 0 时，则表示两个字符串完全相同。</p>
</li>
</ul>
<hr>
<h2 id="2-4-其他重要方法"><a href="#2-4-其他重要方法" class="headerlink" title="2.4. 其他重要方法"></a>2.4. 其他重要方法</h2><ul>
<li><p>indexOf()：查询字符串首次出现的下标位置</p>
</li>
<li><p>lastIndexOf()：查询字符串最后出现的下标位置</p>
</li>
<li><p>contains()：查询字符串中是否包含另一个字符串</p>
</li>
<li><p>toLowerCase()：把字符串全部转换成小写</p>
</li>
<li><p>toUpperCase()：把字符串全部转换成大写</p>
</li>
<li><p>length()：查询字符串的长度</p>
</li>
<li><p>trim()：去掉字符串首尾空格</p>
</li>
<li><p>replace()：替换字符串中的某些字符</p>
</li>
<li><p>split()：把字符串分割并返回字符串数组</p>
</li>
<li><p>join()：把字符串数组转为字符串</p>
</li>
</ul>
<p><strong>String 源码属于所有源码中最基础、最简单的一个，对 String 源码的理解也反应了你的 Java 基础功底。</strong></p>
<blockquote>
<p>String 问题如果再延伸一下，会问到一些更多的知识细节，这也是大厂一贯使用的面试策略，从一个知识点入手然后扩充更多的知识细节，对于 String 也不例外，通常还会关联的询问以下问题：</p>
</blockquote>
<ul>
<li>为什么 String 类型要用 final 修饰？</li>
<li>== 和 equals 的区别是什么？</li>
<li>String 和 StringBuilder、StringBuffer 有什么区别？</li>
<li>String 的 intern() 方法有什么含义？</li>
<li>String 类型在 JVM（Java 虚拟机）中是如何存储的？编译器对 </li>
</ul>
<blockquote>
<p>String 做了哪些优化？接下来我们一起来看这些问题的答案。</p>
</blockquote>
<h1 id="三、知识扩展"><a href="#三、知识扩展" class="headerlink" title="三、知识扩展"></a>三、知识扩展</h1><hr>
<h2 id="3-1-和-equals-的区别"><a href="#3-1-和-equals-的区别" class="headerlink" title="3.1. == 和 equals 的区别"></a>3.1. == 和 equals 的区别</h2><blockquote>
<p>== 对于基本数据类型来说，是用于比较 “值”是否相等的；而对于引用类型来说，是用于比较引用地址是否相同的。</p>
</blockquote>
<p>查看源码我们可以知道 Object 中也有 equals()  方法，源码如下：</p>
<pre class="brush:java">
public boolean equals(Object obj) {
    return (this == obj);
}
</pre>

<blockquote>
<p>可以看出，Object 中的 equals() 方法其实就是 ==，而 String 重写了 equals() 方法把它修改成比较两个字符串的值是否相等。</p>
</blockquote>
<p>源码如下：</p>
<pre class="brush:java">
public boolean equals(Object anObject) {
    // 对象引用相同直接返回 true
    if (this == anObject) {
        return true;
    }
    // 判断需要对比的值是否为 String 类型，如果不是则直接返回 false
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            // 把两个字符串都转换为 char 数组对比
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            // 循环比对两个字符串的每一个字符
            while (n-- != 0) {
                // 如果其中有一个字符不相等就 true false，否则继续对比
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
</pre>

<hr>
<h2 id="3-2-final-修饰的好处"><a href="#3-2-final-修饰的好处" class="headerlink" title="3.2. final 修饰的好处"></a>3.2. final 修饰的好处</h2><blockquote>
<p>从 String 类的源码我们可以看出 String 是被 final 修饰的不可继承类</p>
</blockquote>
<p>源码如下：</p>
<pre class="brush:java">
public final class String 
    implements java.io.Serializable, Comparable<String>, CharSequence { //...... }
</pre>

<p><strong>那这样设计有什么好处呢？</strong></p>
<blockquote>
<p>Java 语言之父 James Gosling 的回答是，他会更倾向于使用 final，因为它能够缓存结果，当你在传参时不需要考虑谁会修改它的值；如果是可变类的话，则有可能需要重新拷贝出来一个新值进行传参，这样在性能上就会有一定的损失。</p>
</blockquote>
<blockquote>
<p>James Gosling 还说迫使 String 类设计成不可变的另一个原因是安全，当你在调用其他方法时，比如调用一些系统级操作指令之前，可能会有一系列校验，如果是可变类的话，可能在你校验过后，它的内部的值又被改变了，这样有可能会引起严重的系统崩溃问题，这是迫使 String 类设计成不可变类的一个重要原因。</p>
</blockquote>
<blockquote>
<p>总结来说，使用 final 修饰的第一个好处是安全；第二个好处是高效，以 JVM 中的字符串常量池来举例，如下两个变量：</p>
</blockquote>
<pre class="brush:java">
String s1 = "java";
String s2 = "java";
</pre>

<blockquote>
<p>只有字符串是不可变时，我们才能实现字符串常量池，字符串常量池可以为我们缓存字符串，提高程序的运行效率，如下图所示：</p>
</blockquote>
<p><img src="https://s1.ax1x.com/2020/07/20/Uf7PaQ.png" alt=""></p>
<blockquote>
<p>试想一下如果 String 是可变的，那当 s1 的值修改之后，s2 的值也跟着改变了，这样就和我们预期的结果不相符了，因此也就没有办法实现字符串常量池的功能了。</p>
</blockquote>
<h2 id="3-3-String-和-StringBuilder、StringBuffer-的区别"><a href="#3-3-String-和-StringBuilder、StringBuffer-的区别" class="headerlink" title="3.3. String 和 StringBuilder、StringBuffer 的区别"></a>3.3. String 和 StringBuilder、StringBuffer 的区别</h2><blockquote>
<p> 因为 String 类型是不可变的，所以在字符串拼接的时候如果使用 String 的话性能会很低，因此我们就需要使用另一个数据类型 StringBuffer，它提供了 append 和 insert 方法可用于字符串的拼接，它使用 synchronized 来保证线程安全，如下源码所示：</p>
</blockquote>
<pre class="brush:java">
@Override
public synchronized StringBuffer append(Object obj) {
    toStringCache = null;
    super.append(String.valueOf(obj));
    return this;
}

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}
</pre>

<blockquote>
<p>因为它使用了 synchronized 来保证线程安全，所以性能不是很高，于是在 JDK 1.5 就有了 StringBuilder，它同样提供了 append 和 insert 的拼接方法，但它没有使用 synchronized 来修饰，因此在性能上要优于 StringBuffer，所以在非并发操作的环境下可使用 StringBuilder 来进行字符串拼接。</p>
</blockquote>
<h2 id="3-4-String-和-JVM"><a href="#3-4-String-和-JVM" class="headerlink" title="3.4. String 和 JVM"></a>3.4. String 和 JVM</h2><blockquote>
<p>String 常见的创建方式有两种，new String() 的方式和直接赋值的方式，直接赋值的方式会先去字符串常量池中查找是否已经有此值，如果有则把引用地址直接指向此值，否则会先在常量池中创建，然后再把引用指向此值；而 new String() 的方式一定会先在堆上创建一个字符串对象，然后再去常量池中查询此字符串的值是否已经存在，如果不存在会先在常量池中创建此字符串，然后把引用的值指向此字符串，如下代码所示：</p>
</blockquote>
<pre class="brush:java">
String s1 = new String("Java");
String s2 = s1.intern();
String s3 = "Java";
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // true
</pre>

<p>它们在 JVM 存储的位置，如下图所示：</p>
<p><img src="https://s1.ax1x.com/2020/07/20/Uf7i5j.png" alt=""></p>
<p>小贴士：JDK 1.7 之后把永生代换成的元空间，把字符串常量池从方法区移到了 Java 堆上。</p>
<p>除此之外编译器还会对 String 字符串做一些优化，例如以下代码：</p>
<pre class="brush:java">
String s1 = "Ja" + "va";
String s2 = "Java";
System.out.println(s1 == s2);
</pre>

<p>虽然 s1 拼接了多个字符串，但对比的结果却是 true，我们使用反编译工具，看到的结果如下：</p>
<pre class="brush:java">
Compiled from "StringExample.java"
public class com.lagou.interview.StringExample {
  public com.lagou.interview.StringExample();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
    LineNumberTable:
      line 3: 0

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String Java
       2: astore_1
       3: ldc           #2                  // String Java
       5: astore_2
       6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       9: aload_1
      10: aload_2
      11: if_acmpne     18
      14: iconst_1
      15: goto          19
      18: iconst_0
      19: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
      22: return
    LineNumberTable:
      line 5: 0
      line 6: 3
      line 7: 6
      line 8: 22
}
</pre>

<blockquote>
<p>从编译代码 #2 可以看出，代码 “Ja”+”va” 被直接编译成了 “Java” ，因此 s1==s2 的结果才是 true，这就是编译器对字符串优化的结果。</p>
</blockquote>
<p><strong>小结</strong></p>
<p><strong>从 String 的源码入手，重点写了 String 的构造方法、equals() 方法和 compareTo() 方法，其中 equals() 重写了 Object 的 equals() 方法，把引用对比改成了字符串值对比，也介绍了 final 修饰 String 的好处，可以提高效率和增强安全性，同时我们还介绍了 String 和 JVM 的一些执行细节。</strong></p>

      
       <hr><span style="font-style: italic;color: gray;"> 转载请注明来源，欢迎对文章中的引用来源进行考证，欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论，也可以邮件至 jaytp@qq.com </span>
    </div>
</article>


<p>
    <a  class="dashang" onclick="dashangToggle()">💰</a>
</p>






    




    </div>
    <div class="copyright">
        <p class="footer-entry">
    ©2016-2020 Yelog
</p>
<p class="footer-entry">Built with <a href="https://hexo.io/" target="_blank">Hexo</a> and <a href="https://github.com/yelog/hexo-theme-3-hexo" target="_blank">3-hexo</a> theme</p>

    </div>
    <div class="full-toc">
        <button class="full" data-title="切换全屏 快捷键 s"><span class="min "></span></button>
<a class="" id="rocket" ></a>

    </div>
</div>

<div class="hide_box" onclick="dashangToggle()"></div>
<div class="shang_box">
    <a class="shang_close"  onclick="dashangToggle()">×</a>
    <div class="shang_tit">
        <p>Help us with donation</p>
    </div>
    <div class="shang_payimg">
        <div class="pay_img">
            <img src="/img/alipay.jpg" class="alipay" title="扫码支持">
            <img src="/img/weixin.jpg" class="weixin" title="扫码支持">
        </div>
    </div>
    <div class="shang_payselect">
        <span><label><input type="radio" name="pay" checked value="alipay">alipay</label></span><span><label><input type="radio" name="pay" value="weixin">weixin</label></span>
    </div>
</div>


</body>
<script src="/js/jquery.pjax.js?v=1.1.0" ></script>

<script src="/js/script.js?v=1.1.0" ></script>
<script>
    var img_resize = 'default';
    function initArticle() {
        /*渲染对应的表格样式*/
        
            $("#post .pjax table").addClass("green_title");
        

        /*渲染打赏样式*/
        
        $("input[name=pay]").on("click", function () {
            if($("input[name=pay]:checked").val()=="weixin"){
                $(".shang_box .shang_payimg .pay_img").addClass("weixin_img");
            } else {
                $(".shang_box .shang_payimg .pay_img").removeClass("weixin_img");
            }
        })
        

        /*高亮代码块行号*/
        

        /*访问数量*/
        
        $.getScript("//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js");
        

        /*代码高亮，行号对齐*/
        $('.pre-numbering').css('line-height',$('.has-numbering').css('line-height'));

        
        
    }

    /*打赏页面隐藏与展示*/
    
    function dashangToggle() {
        $(".shang_box").fadeToggle();
        $(".hide_box").fadeToggle();
    }
    

</script>

<!--加入行号的高亮代码块样式-->

<!--自定义样式设置-->
<style>
    
    
    .nav {
        width: 542px;
    }
    .nav.fullscreen {
        margin-left: -542px;
    }
    .nav-left {
        width: 120px;
    }
    
    
    @media screen and (max-width: 1468px) {
        .nav {
            width: 492px;
        }
        .nav.fullscreen {
            margin-left: -492px;
        }
        .nav-left {
            width: 100px;
        }
    }
    
    
    @media screen and (max-width: 1024px) {
        .nav {
            width: 492px;
            margin-left: -492px
        }
        .nav.fullscreen {
            margin-left: 0;
        }
    }
    
    @media screen and (max-width: 426px) {
        .nav {
            width: 100%;
        }
        .nav-left {
            width: 100%;
        }
    }
    
    
    .nav-right .title-list nav a .post-title, .nav-right .title-list #local-search-result a .post-title {
        color: #383636;
    }
    
    
    .nav-right .title-list nav a .post-date, .nav-right .title-list #local-search-result a .post-date {
        color: #5e5e5f;
    }
    
    
    .nav-right nav a.hover, #local-search-result a.hover{
        background-color: #e2e0e0;
    }
    
    

    /*列表样式*/
    

    /* 背景图样式 */
    
    


    /*引用块样式*/
    

    /*文章列表背景图*/
    

    
</style>







</html>
